/*
 *  CEScrollMenu.cpp
 *  LID Library
 *
 *  Created by Alexander Trutchenko on 09/11/11.
 *  Copyright 2011 League of Independent Developers. All rights reserved.
 *
 */

#include "cocos2dx_extentions/controls/CEScrollMenu.h"

#include "cocos2dx_extentions/controls/CEScrollView.h"
#include "cocos2dx_extentions/utility/CECocos2dUtility.h"

using namespace cocos2d;

namespace cocosext {

#define CE_SCROLL_MENU_MOVE_DEVIATION 5.f

/////////////////////////////////////////////////////
//
/** CEScrollMenu 
* 
*/
/////////////////////////////////////////////////////

CEScrollMenu* CEScrollMenu::node(int touchPriority, CEScrollView* scrollView)
{
	CEScrollMenu *pRet = new CEScrollMenu(touchPriority, scrollView);
	CCAssert(pRet != NULL, NULL);
	if (pRet->init())
	{
		pRet->autorelease();
        return pRet;
	}
	else
	{
		CC_SAFE_DELETE(pRet)
		return NULL;
	}
}

/////////////////////////////////////////////////////
//
CEScrollMenu::CEScrollMenu(int touchPriority, CEScrollView* scrollView)
: CEMenu(touchPriority)
, _scrollView(scrollView)
, _scrollViewTouchBegan(false)
, _scrollViewTouchLost(false)
, _activateTimerExpired(false)
{

}

bool CEScrollMenu::init()
{
    if (!CCMenu::init())
        return false;


	return true;
}

/////////////////////////////////////////////////////
// public Cocos2d interface


//////////////////////////////////////////////////////
// Touch processing
bool CEScrollMenu::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
	if (!isNodeContainsTouch(*_scrollView, pTouch))
		return false;

	if (_scrollView->isSelfMoving())
		return false;

//From CCMenu
    CC_UNUSED_PARAM(pEvent);
	if (m_eState != kCCMenuStateWaiting || ! m_bIsVisible)
		return false;

	for (CCNode *c = this->m_pParent; c != NULL; c = c->getParent())
		if (c->getIsVisible() == false)
			return false;

	m_pSelectedItem = this->itemForTouch(pTouch);
//CEScrollMenu changes
	if (m_pSelectedItem == NULL)
		return false;

	m_eState = kCCMenuStateTrackingTouch;
	_activateTimerExpired = false;
	this->schedule(schedule_selector(CEScrollMenu::onActivateTimerExpired), CE_SCROLLMENU_ITEM_ACTIVATE_TIME);
	_scrollTapTimerExpired = false;
	this->schedule(schedule_selector(CEScrollMenu::onTapTimerExpired), CE_SCROLLMENU_ITEM_TAP_TIME);
	_scrollViewTouchBegan = _scrollView->ccTouchBegan(pTouch, pEvent);
	_scrollViewTouchLost = false;
	_startPoint = pTouch->locationInView(pTouch->view());

	return true;
}


void CEScrollMenu::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
{
	if (_scrollViewTouchBegan)
	{
		_scrollView->ccTouchMoved(pTouch, pEvent);
		if (!_scrollViewTouchLost && _scrollView->isMovedOnLatestTouchMove() && fabs(_scrollView->moveDeltaVertically()) > CE_SCROLL_MENU_MOVE_DEVIATION)
		{
			this->unschedule(schedule_selector(CEScrollMenu::onActivateTimerExpired));
			this->unschedule(schedule_selector(CEScrollMenu::onTapTimerExpired));
			_scrollViewTouchLost = true;
			return;
		}
	}
	if (!_scrollViewTouchLost)
	{
        CC_UNUSED_PARAM(pEvent);
		CCAssert(m_eState == kCCMenuStateTrackingTouch, "[Menu ccTouchMoved] -- invalid state");
		CCMenuItem *currentItem = this->itemForTouch(pTouch);
		if (currentItem != m_pSelectedItem) 
		{
			if (m_pSelectedItem != NULL)
			{
				if (_activateTimerExpired)
					m_pSelectedItem->unselected();
				else
					this->unschedule(schedule_selector(CEScrollMenu::onActivateTimerExpired));
				m_pSelectedItem = NULL;
			}
		}
//		CCMenu::ccTouchMoved(pTouch, pEvent);
	}
}

void CEScrollMenu::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
	if (_scrollViewTouchBegan)
		_scrollView->ccTouchEnded(pTouch, pEvent);
	this->unschedule(schedule_selector(CEScrollMenu::onActivateTimerExpired));
	this->unschedule(schedule_selector(CEScrollMenu::onTapTimerExpired));

//	CCMenu
	CCAssert(m_eState == kCCMenuStateTrackingTouch, "[Menu ccTouchEnded] -- invalid state");
	if (m_pSelectedItem)
	{
		if (!_activateTimerExpired && !_scrollViewTouchLost)
			m_pSelectedItem->selected();
		m_pSelectedItem->unselected();
		if (!_scrollTapTimerExpired &&
			!_scrollViewTouchLost && 
			fabs(_startPoint.y - pTouch->locationInView(pTouch->view()).y) < CE_SCROLL_MENU_MOVE_DEVIATION &&
			fabs(_startPoint.x - pTouch->locationInView(pTouch->view()).x) < CE_SCROLL_MENU_MOVE_DEVIATION)
			m_pSelectedItem->activate();
	}
	m_eState = kCCMenuStateWaiting;
}

void CEScrollMenu::ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent)
{
	if (_scrollViewTouchBegan)
		_scrollView->ccTouchCancelled(pTouch, pEvent);
	this->unschedule(schedule_selector(CEScrollMenu::onActivateTimerExpired));
	this->unschedule(schedule_selector(CEScrollMenu::onTapTimerExpired));

//	CCMenu
	CCAssert(m_eState == kCCMenuStateTrackingTouch, "[Menu ccTouchEnded] -- invalid state");
	if (m_pSelectedItem)
	{
		if (!_activateTimerExpired && !_scrollViewTouchLost)
			m_pSelectedItem->selected();
		m_pSelectedItem->unselected();
	}
	m_eState = kCCMenuStateWaiting;
}

/////////////////////////////////////////////////////
// private interface

void CEScrollMenu::onActivateTimerExpired(ccTime delta)
{
	this->unschedule(schedule_selector(CEScrollMenu::onActivateTimerExpired));
	m_pSelectedItem->selected();
	_activateTimerExpired = true;
}

void CEScrollMenu::onTapTimerExpired(ccTime delta)
{
	this->unschedule(schedule_selector(CEScrollMenu::onTapTimerExpired));
	_scrollTapTimerExpired = true;
}

}; // end namespace cocosext

